#pragma once

#include <iostream>
#include <vector>
#include <pthread.h>

#include "sem.hpp"
#include "mutex.hpp"

namespace RingBufferModule
{
    using namespace SemMudule;
    using namespace MutexModule;

    template <typename T>
    class ringbuffer
    {
    public:
        ringbuffer(int cap) // cap为外界传进来的环形队列的大小
            : _size(cap),
              _buffer(cap),
              _psem(cap),
              _csem(0),
              _p_step(0),
              _c_step(0)
        {
        }

        void Equeue(const T &in) // 采取引用传参，减少拷贝
        {

            _psem.P();

            {
                LockGuard lockguard(_p_lock);
                _buffer[_p_step] = in;
                _p_step++;
                _p_step %= _size;
            }
            _csem.V();
        }

        void Pop(T *out)
        {
            _csem.P();

            {
                LockGuard lockguard(_c_lock);
                *out = _buffer[_c_step];
                _c_step++;
                _c_step %= _size;
            }
            _psem.V();
        }
        ~ringbuffer()
        {
        }

    private:
        std::vector<T> _buffer; // 环形缓冲区
        size_t _size;           // 缓冲区大小

        sem _psem; // 生产者信号量,代表的是剩余空间
        sem _csem; // 消费者信号量,代表的是剩余数据

        size_t _p_step; // 生产者下标
        size_t _c_step; // 消费者下标

        Mutex _p_lock;
        Mutex _c_lock;
    };
}